#include "HdfsClient.h"
#include <HTTPLib/httplib.h>
#include <utility>

using namespace std;
using namespace httplib;

HdfsClient::HdfsClient(std::string  ip, int port): ip(std::move(ip)), port(port) { }

HdfsClient::~HdfsClient() = default;

bool HdfsClient::Ok()
{
    Client client(ip, port);
    auto resp = client.Get("/");
    if (!resp)
        return false;
    if (resp->status != 200)
        return false;
    return true;
}

bool HdfsClient::UploadFile(const string &path, const string &filePath)
{
    ifstream file;
    file.open(filePath, ios::binary | ios::ate);
    string body;
    if (file.is_open())
    {
        int length = file.tellg();
        char chars[length];
        file.seekg(0, ios::beg);
        file.read(chars, length);
        file.close();
        body.append(chars, length);
        return UploadContent(path, body);
    }
    return false;
}

bool HdfsClient::UploadContent(const string &path, const string &content)
{
    auto urlPath = stringstream();
    urlPath << "/webhdfs/v1" << CheckPath(path) << "?op=CREATE&user.name=root&data=true&overwrite=true";
    Client client(ip, port);
    auto resp = client.Put(urlPath.str().c_str(), content, "application/octet-stream");
    if (!resp)
        return false;
    if (resp->status == 201)
        return true;
    return false;
}

bool HdfsClient::DownloadFile(const string &path, const string &filePath)
{
    string content;
    if (!DownloadContent(path, content))
        return false;
    ofstream file;
    file.open(filePath, ios::trunc);
    if (file.is_open())
    {
        file << content;
        file.flush();
        file.close();
        return true;
    }
    return false;
}

bool HdfsClient::DownloadContent(const string &path, string &content)
{
    auto urlPath = stringstream();
    urlPath << "/webhdfs/v1" << CheckPath(path) << "?op=OPEN&user.name=root";
    Client client(ip, port);
    auto resp = client.Get(urlPath.str().c_str());
    if (!resp)
        return false;
    if (resp->status != 200)
        return false;
    content = resp->body;
    return true;
}

bool HdfsClient::DeleteFile(const string &path)
{
    auto urlPath = stringstream();
    urlPath << "/webhdfs/v1" << CheckPath(path) << "?op=DELETE&user.name=root";
    Client client(ip, port);
    auto resp = client.Delete(urlPath.str().c_str());
    if (!resp)
        return false;
    if (resp->status != 200)
        return false;
    return true;
}

std::string HdfsClient::CheckPath(const string &path)
{
    if (path.empty())
        return path;
    if(path[0] == '/')
        return path;
    return string("/") + path;
}
